﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Resources;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;

namespace DemoApp.DataAccess
{
    /// <summary>
    ///     Represents a source of customers in the application.
    /// </summary>
    internal class CustomerDb : ICustomerDb
    {
        #region Fields

        private readonly string _customerDataFile;
        private IEnumerable<CustomerDao> _customers;

        #endregion // Fields

        #region Constructor

        /// <summary>
        ///     Creates a new repository of customers.
        /// </summary>
        /// <param name="customerDataFile">The relative path to an XML resource file that contains customer data.</param>
        public CustomerDb(string customerDataFile)
        {
            _customerDataFile = customerDataFile;
        }

        #endregion // Constructor

        #region Public Interface        

        /// <summary>
        ///     Returns a shallow-copied list of all customers in the repository.
        /// </summary>
        public IEnumerable<CustomerDao> GetCustomers()
        {
            
            if (File.Exists("Customers.xml"))
            {
                //Deserialize
                var xr = new XmlRootAttribute("customers");
                var serializer = new XmlSerializer(typeof(CustomerDao[]), xr);
                using (var fs = new FileStream("Customers.xml", FileMode.Open))
                {
                    _customers = (CustomerDao[])serializer.Deserialize(fs);
                }
            }
            else
            {
                _customers = LoadCustomers(_customerDataFile);
                //Serialize
                var xr = new XmlRootAttribute("customers");
                var serializer = new XmlSerializer(typeof(CustomerDao[]), xr);
                using (var writer = new StreamWriter("customers.xml"))
                {
                    serializer.Serialize(writer, _customers.ToArray());
                }
            }
            return new List<CustomerDao>(_customers);
        }

        public bool AddCustomer(double totalSales, string firstName, string lastName, bool isCompany, string email)
        {
            //add a customer into the xmlfile  
            XDocument document = XDocument.Load("customers.xml");
            var customer = new XElement("CustomerDao",
                                        new XAttribute("LastName",lastName),
                                        new XElement("Email", email),
                                        new XElement("TotalSales", totalSales),
                                        new XElement("FirstName", firstName),
                                        new XElement("IsCompany", isCompany)
                                        );
            document.Root.Add(customer);
            document.Save("customers.xml");
            return true;
        }

        #endregion // Public Interface

        #region Private Helpers

        //this method provides a start up customer list.... to be used for development and to be deleted later
        private static IEnumerable<CustomerDao> LoadCustomers(string customerDataFile)
        {
            // In a real application, the data would come from an external source,
            // but for this demo let's keep things simple and use a resource file.
            using (Stream stream = GetResourceStream(customerDataFile))
            {
                using (XmlReader xmlRdr = new XmlTextReader(stream))
                {
                    IEnumerable<XElement> customers = XDocument.Load(xmlRdr).Element("customers").Elements("customer");
                    return
                        (from customerElem in customers
                         select new CustomerDao
                             {
                                 TotalSales = (double) customerElem.Attribute("totalSales"),
                                 FirstName = (string) customerElem.Attribute("firstName"),
                                 LastName = (string) customerElem.Attribute("lastName"),
                                 IsCompany = (bool) customerElem.Attribute("isCompany"),
                                 Email = (string) customerElem.Attribute("email")
                             }).ToList();
                }
            }
        }

        private static Stream GetResourceStream(string resourceFile)
        {
            var uri = new Uri(resourceFile, UriKind.RelativeOrAbsolute);

            StreamResourceInfo info = Application.GetResourceStream(uri);
            if (info == null || info.Stream == null)
                throw new ApplicationException("Missing resource file: " + resourceFile);

            return info.Stream;
        }

        #endregion // Private Helpers
    }
}